/* eslint-disable react/forbid-prop-types,consistent-return,radix */
import React from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'antd';

import Icons from './Icon';
import less from './style.less';

export default class ImgPreview extends React.Component {
  static propTypes = {
    currentImage: PropTypes.number,
    enableKeyboardInput: PropTypes.bool,
    height: PropTypes.number,
    images: PropTypes.arrayOf(
      PropTypes.shape({
        src: PropTypes.string,
        srcset: PropTypes.array,
      }),
    ).isRequired,
    onClose: PropTypes.func.isRequired,
    showCloseButton: PropTypes.bool,
    hasRotate: PropTypes.bool,
    visible: PropTypes.bool,
  };

  static defaultProps = {
    enableKeyboardInput: true,
    currentImage: 0,
    height: 600,
    hasRotate: true,
    showCloseButton: true,
    visible: true,
  };

  constructor(props) {
    super(props);

    this.state = {
      currentDeg: 0,
      currentImage: this.props.currentImage || 0,
      visible: this.props.visible || false,
    };
  }

  componentDidMount() {
    if (this.props.enableKeyboardInput) {
      window.addEventListener('keydown', this.handleKeyboardInput);
    } else {
      window.removeEventListener('keydown', this.handleKeyboardInput);
    }
  }

  componentWillReceiveProps(nextProps, prevProps) {
    if (nextProps.currentImage !== prevProps.currentImage) {
      this.setState({
        currentImage: nextProps.currentImage,
      });
    }
    if (nextProps.visible !== prevProps.visible) {
      this.setState({
        visible: nextProps.visible,
      });
    }
  }

  componentWillUnmount() {
    if (this.props.enableKeyboardInput) {
      window.removeEventListener('keydown', this.handleKeyboardInput);
    }
  }

  gotoPrev = event => {
    if (this.state.currentImage === 0) return;
    if (event) {
      event.preventDefault();
      event.stopPropagation();
    }
    this.setState({
      currentImage: this.state.currentImage - 1,
    });
  };

  gotoNext = event => {
    if (this.state.currentImage === this.props.images.length - 1) return;
    if (event) {
      event.preventDefault();
      event.stopPropagation();
    }
    this.setState({
      currentImage: this.state.currentImage + 1,
    });
  };

  rotateLeft = event => {
    if (event) {
      event.preventDefault();
      event.stopPropagation();
    }
    let deg = this.state.currentDeg || 0;
    deg -= 90;
    this.setState({
      currentDeg: deg,
    });
  };

  rotateRight = event => {
    if (event) {
      event.preventDefault();
      event.stopPropagation();
    }
    let deg = this.state.currentDeg || 0;
    deg += 90;
    this.setState({
      currentDeg: deg,
    });
  };

  handleKeyboardInput = event => {
    if (this.props.visible === false) {
      // 弹窗只是隐藏的时候不触发事件绑定
      return false;
    }

    if (event.keyCode === 37) {
      this.gotoPrev();
    } else if (event.keyCode === 39) {
      this.gotoNext();
    } else if (event.keyCode === 27) {
      this.props.onClose();
    } else {
      return false;
    }
  };

  close = () => {
    this.setState({
      visible: false,
    });
    this.props.onClose && this.props.onClose();
  };

  renderArrowPrev = () => {
    if (this.state.currentImage === 0) return;

    return (
      <button
        type="button"
        className="arrow arrow-prev"
        onClick={this.gotoPrev}
        onTouchEnd={this.gotoPrev}
      >
        <Icons type="arrowLeft" />
      </button>
    );
  };

  renderArrowNext = () => {
    if (this.state.currentImage === this.props.images.length - 1) return;

    return (
      <button
        type="button"
        className="arrow arrow-next"
        onClick={this.gotoNext}
        onTouchEnd={this.gotoNext}
      >
        <Icons type="arrowRight" />
      </button>
    );
  };

  renderRotate = () => {
    if (this.props.hasRotate) {
      return (
        <div className="rotate">
          <div
            className="rotate-left"
            key="left"
            onClick={this.rotateLeft}
            onTouchEnd={this.rotateLeft}
          >
            <Icon className="close-btn" type="undo" />
          </div>
          <div
            className="rotate-right"
            key="right"
            onClick={this.rotateRight}
            onTouchEnd={this.rotateRight}
          >
            <Icon className="close-btn" type="redo" />
          </div>
        </div>
      );
    }
  };

  renderCloseButton() {
    if (!this.props.showCloseButton) return;
    return <Icon className="close-btn" type="close" onClick={this.close} />;
  }

  renderCurrentIndex() {
    return (
      <div className="index-text">
        {this.state.currentImage + 1} / {this.props.images.length}
      </div>
    );
  }

  renderDialog() {
    return (
      <div className="dialog" key="dialog">
        {this.renderCurrentIndex()}
        {this.renderImages()}
        {this.renderArrowPrev()}
        {this.renderArrowNext()}
        {this.renderRotate()}
        {this.renderCloseButton()}
      </div>
    );
  }

  renderImages = () => {
    const { currentImage } = this.state;
    const { images } = this.props;
    if (!images || !images.length) return;

    let width = '100%';
    const transform = `rotate(${this.state.currentDeg}deg)`;
    let maxWidth = '80%';

    if (this.state.currentDeg % 90 === 0 && this.state.currentDeg % 180 !== 0) {
      width = this.props.height;
      maxWidth = '100%';
    }

    const imgStyle = { maxWidth };

    let img;

    if (images[currentImage].srcset) {
      img = (
        <img
          className="image"
          alt=""
          src={images[currentImage].src}
          srcSet={images[currentImage].srcset.join()}
          sizes={`${parseInt(imgStyle.maxWidth)}vw`}
          style={imgStyle}
          onTouchEnd={e => e.stopPropagation()}
          onClick={e => e.stopPropagation()}
        />
      );
    } else {
      img = (
        <img
          className="image"
          alt=""
          src={images[currentImage].src}
          style={imgStyle}
          onTouchEnd={e => e.stopPropagation()}
          onClick={e => e.stopPropagation()}
        />
      );
    }
    const constainerStyle = {
      height: '100%',
      margin: 'auto',
      width,
      transform,
    };

    return (
      <div key={`image${currentImage}`} style={constainerStyle}>
        {img}
      </div>
    );
  };

  render() {
    return this.state.visible ? (
      <div className={less.imgPreview}>{this.renderDialog()}</div>
    ) : null;
  }
}
